#include "clientview.h"
#include "ui_clientview.h"

ClientView::ClientView(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ClientView)
{
    ui->setupUi(this);
    init();
}

void ClientView::init()
{
    QScreen* screen = QGuiApplication::primaryScreen();
    ui->leftWidget->setMaximumWidth(screen->availableGeometry().width()/5);

    // TCP/UDP连接
    connect(ui->TCPConnectBtn,&QPushButton::clicked,this,&ClientView::onTcpConnectBtn);
    connect(ui->UDPConnectBtn,&QPushButton::clicked,this,&ClientView::onUdpConnectBtn);

    // 发送数据btn
    connect(ui->sendDataBtn,&QPushButton::clicked,this,&ClientView::onSendBtnClicked);

    // 清空文本
    connect(ui->sendClearBtn,&QPushButton::clicked,this,&ClientView::onSendClearBtnClicked);
    connect(ui->recvClearBtn,&QPushButton::clicked,this,&ClientView::onRecvClearBtnClicked);
}

ClientView::~ClientView()
{
    delete ui;

    if(m_tcp!=nullptr){
        m_tcp->disconnect();
        m_tcp->disconnectFromHost();
//        m_tcp->deleteLater(); // 智能指针管理
//        m_tcp = nullptr;
    }
}

// tcp连接按钮
void ClientView::onTcpConnectBtn()
{
    if(m_tcp==nullptr){
        m_tcp = QSharedPointer<QTcpSocket>(new QTcpSocket);
        connect(m_tcp.get(),&QTcpSocket::connected,this,&ClientView::onConnection);
        connect(m_tcp.get(),&QTcpSocket::stateChanged,this,&ClientView::onTCPStateChanged);
        connect(m_tcp.get(),&QTcpSocket::readyRead,this,&ClientView::onTCPReadyRead);
        connect(ui->TCPCloseBtn,&QPushButton::clicked,this,&ClientView::onDisconnected);
        connect(m_tcp.get(),&QTcpSocket::disconnected,this,&ClientView::onDisconnected);
    }
//    ui->UDPConnectBtn->setEnabled(false);
//    ui->UDPCloseBtn->setEnabled(false);
    QString ip = ui->targetIPLine->text();
    int port = ui->targetPortLine->text().toInt();
    m_tcp->connectToHost(ip,static_cast<quint16>(port));
    if(!ui->randomLocalPort->isChecked()){
        quint16 port = static_cast<quint16>(ui->localPortLine->text().toInt());
        qDebug() << "local port: "<< port;
        if(!m_tcp->bind(QHostAddress::Any,port)){
            QMessageBox::information(this,"bind","bind to port failed!");
        }
    }
    if(m_tcp->waitForConnected()){
        m_connected = true;
    }else{
        qDebug() << "connected faild!";
        m_connected = false;
        onConnectFaild();
    }
}

// tcp连接
void ClientView::onConnection()
{
    QString info = m_tcp->peerAddress().toString() + ":" + QString::asprintf("%1").arg(m_tcp->peerPort());
    QMessageBox::information(this,"connect",info);
}

// tcp连接状态改变
void ClientView::onTCPStateChanged(QAbstractSocket::SocketState sockState)
{
    m_stateDialog->setState(sockState);
    if(sockState == QTcpSocket::BoundState){
        qDebug() << "tcp state: bound";
    }else if(sockState == QTcpSocket::ClosingState){
        m_stateDialog->setInfo("tcp state: closed");
    }else if(sockState == QTcpSocket::ConnectedState){
        m_stateDialog->setInfo("tcp state: connected");
    }else if(sockState == QTcpSocket::ConnectingState){
        m_stateDialog->setInfo("tcp state: connecting");
    }else if(sockState == QTcpSocket::HostLookupState){
         m_stateDialog->setInfo("tcp state: HostLookupState");
    }else if(sockState == QTcpSocket::UnconnectedState){
         m_stateDialog->setInfo("tcp state: UnconnectedState");
    }else if(sockState == QTcpSocket::ListeningState){
         m_stateDialog->setInfo("tcp state: ListeningState");
    }else{
         m_stateDialog->setInfo("tcp state: unknown!");
    }
    m_stateDialog->open();
}

// tcp断开连接，关闭tcpsocket，还是有点问题，不知道怎么delete掉这个tcp*
void ClientView::onDisconnected()
{
    if(m_tcp!=nullptr){
        m_tcp->disconnect();
        m_tcp->close(); // 会调用disconnectFromHost
//        m_tcp->disconnectFromHost();
//        m_tcp->deleteLater(); // 智能指针管理，不需要delete
        m_tcp = nullptr;
//        m_tcp->setSocketState()
        qDebug()<<"connect disconnected!";
    }
}

// tcp准备读取
void ClientView::onTCPReadyRead()
{
    // QByteArray 转 QString
    QByteArray byteArr = m_tcp->readAll();
    auto s = QString(byteArr);
    int hasReadBytes = ui->ByteRecvedLine->text().toInt();
    hasReadBytes+=s.size();
    ui->ByteRecvedLine->setText(QString::asprintf("%1").arg(hasReadBytes));
    ui->recvTextEdit->append(s);
}

// 清除发送文本编辑框
void ClientView::onSendClearBtnClicked()
{
    ui->sendTextEdit->clear();
    ui->ByteSendLine->setText("0");
}

// 清除接收文本编辑框
void ClientView::onRecvClearBtnClicked()
{
    ui->recvTextEdit->clear();
    ui->ByteRecvedLine->setText("0");
}

// 连接失败
void ClientView::onConnectFaild()
{
//    QMessageBox::warning(this,"TCP connect","TCP connect failed!");
    ui->TCPCloseBtn->setEnabled(true);
    ui->UDPCloseBtn->setEnabled(true);
    ui->TCPConnectBtn->setEnabled(true);
    ui->UDPConnectBtn->setEnabled(true);
}

// udp连接按钮
void ClientView::onUdpConnectBtn()
{
    if(m_udp==nullptr){
        m_udp = QSharedPointer<QUdpSocket>(new QUdpSocket);
        qDebug() << "new udpsocket";
    }
    connect(m_udp.get(),&QUdpSocket::readyRead,this,&ClientView::onUDPReadyRead);
    connect(m_udp.get(),&QUdpSocket::stateChanged,this,&ClientView::onUDPStateChanged);
//    connect(m_udp,&QUdpSocket::,this,&ClientView::onUDPStateChanged);
//    ui->UDPConnectBtn->setEnabled(false);
//    ui->UDPCloseBtn->setEnabled(false);
    m_UdpTargetIP = ui->targetIPLine->text();
    m_UdpPort = ui->targetPortLine->text();
    // 是否绑定随机端口
    if(!ui->randomLocalPort->isChecked()){
        if(!m_udp->bind(QHostAddress::Any,ui->localPortLine->text().toUInt())){
            qDebug() << "udp bind: " << "127.0.0.1" << ":" << m_udp->localPort();
            return;
        }else{
            qDebug() << "udp bind: " << "127.0.0.1" << ":" << m_udp->localPort();
            QMessageBox::warning(this,"bind","udp bind failed!");
        }
    }else{
        if(!m_udp->bind(QHostAddress::Any,0,QUdpSocket::ShareAddress)){ // port 为 0，随机绑定一个端口
            qDebug() << "udp bind: " << "127.0.0.1" << ":" << m_udp->localPort();
            return;
        }else{
            qDebug() << "udp bind: " << "127.0.0.1" << ":" << m_udp->localPort();
            QMessageBox::warning(this,"bind","udp bind failed! "+m_udp->error());
        }
    }
}

// udp准备读取
void ClientView::onUDPReadyRead()
{
    while(m_udp->hasPendingDatagrams()){
        QByteArray datagram;
        datagram.resize(static_cast<int>(m_udp->pendingDatagramSize()));
        QHostAddress senderAddr;
        quint16 senderPort;
        m_udp->readDatagram(datagram.data(),datagram.size(),&senderAddr,&senderPort);
        QString msg = QString::fromUtf8(datagram);
        int hasReadBytes = ui->ByteRecvedLine->text().toInt();
        hasReadBytes+=msg.size();
        ui->ByteRecvedLine->setText(QString::asprintf("%1").arg(hasReadBytes));
        ui->recvTextEdit->append(msg);
    }
}

// udp状态改变
void ClientView::onUDPStateChanged(QAbstractSocket::SocketState sockState)
{
    if(sockState == QUdpSocket::BoundState){
        QMessageBox::information(this,"udp state","udp state: bound");
    }else if(sockState == QUdpSocket::ClosingState){
        QMessageBox::information(this,"udp state","udp state: close");
    }else if(sockState == QUdpSocket::ConnectedState){
        QMessageBox::information(this,"udp state","udp state: connected");
    }else if(sockState == QUdpSocket::ConnectingState){
        QMessageBox::information(this,"udp state","udp state: connecting");
    }else if(sockState == QUdpSocket::HostLookupState){
        QMessageBox::information(this,"udp state","udp state: HostLookupState");
    }else if(sockState == QUdpSocket::UnconnectedState){
        QMessageBox::information(this,"udp state","udp state: UnconnectedState");
    }else if(sockState == QUdpSocket::ListeningState){
        QMessageBox::information(this,"udp state","udp state: ListeningState");
    }else{
        QMessageBox::information(this,"udp state","udp state: unknown!");
    }
}

// 关闭udpsocket，还是有点问题，不知道怎么delete掉这个udp*
void ClientView::onUDPCloseBtnClick()
{
    if(m_udp != nullptr){
//        m_udp->deleteLater(); // 智能指针管理
//        m_udp = nullptr;
    }
}

void ClientView::onSendBtnClicked()
{
    QString str = ui->sendTextEdit->toPlainText();
    int hasSendBytes = ui->ByteSendLine->text().toInt();
    hasSendBytes+=str.size();
    ui->ByteSendLine->setText(QString::asprintf("%1").arg(hasSendBytes));
    qDebug() <<"tcp has sent bytes: " << hasSendBytes;
    if(m_tcp!=nullptr){
        m_tcp->write(str.toStdString().c_str());
        qDebug() <<"tcp: "<< str;
    }
    if(m_udp!=nullptr){
        m_udp->writeDatagram(str.toUtf8(),QHostAddress(m_UdpTargetIP),static_cast<quint16>(m_UdpPort.toInt()));
        qDebug() <<"udp: "<< str;
    }
}

